package com.example.lj.uav.view.fragment;

import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.StatFs;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;

import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.model.LatLng;
import com.example.lj.uav.MyApplication;
import com.example.lj.uav.R;
import com.example.lj.uav.adapter.SpinnerDropDownAdapter;
import com.example.lj.uav.bean.RouteLine;
import com.example.lj.uav.bean.RoutePoint;
import com.example.lj.uav.utils.DoubleUtils;
import com.example.lj.uav.utils.OnUIUtils;
import com.example.lj.uav.view.RouteSettingActivity;

import org.dom4j.util.StringUtils;

import java.io.File;
import java.text.NumberFormat;
import java.util.List;

import dji.common.battery.BatteryState;
import dji.common.camera.StorageState;
import dji.common.flightcontroller.CompassCalibrationState;
import dji.common.flightcontroller.CompassState;
import dji.common.flightcontroller.imu.IMUState;
import dji.common.flightcontroller.imu.SensorState;
import dji.sdk.battery.Battery;
import dji.sdk.camera.Camera;
import dji.sdk.flightcontroller.Compass;
import dji.sdk.flightcontroller.FlightController;

import static com.example.lj.uav.MyApplication.mPref;

public class FragmentFlyPrepare extends Fragment implements View.OnClickListener,Handler.Callback {
    private TextView mTvCancel;
    private TextView mTvSpeed;
    private TextView mTvEle;
    private TextView mTvCapacity;
    private TextView mTvDistance;
    private TextView mTvMode;
    private TextView mTvCampass;
    private TextView mTvIMU;
    private TextView mTvGPS;
    private TextView mTvResult;
    private ImageView mIvReduce;
    private ImageView mIvPlus;
    private Spinner mSpFinishAction;
    private Spinner mSpLoseCtrlAction;
    private SeekBar mSbBar;

    private RouteLine line;
    private RouteSettingActivity mActivity;
    private List<Battery> battery;
    private String[] actionIds = {"Hover","GoHome","AutoLand","GoFirstPoint"};//悬停，自动返航，原地降落，返回航线起始点
    private String[] actions = {"悬停","自动返航","原地降落","返回航线起始点"};
    private String[] loseActions = {"悬停","自动返航"};
    private SpinnerDropDownAdapter actionAdapter;
    private SpinnerDropDownAdapter loseCtrlAdapter;
    private FlightController mFlightController;
    private double speed;
    private int progressPercent;
    private boolean seekBarDragging;
    private boolean imuOk;
    private boolean gpsOk;
    private boolean compassOk;
    private String batteryCapacity;
    private Camera camera;
    private Handler handler;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_fly_prepare,null);
        mTvCancel = view.findViewById(R.id.tv_fly_prepare_cancel);
        mTvSpeed = view.findViewById(R.id.tv_fly_prepare_speed);
        mTvEle = view.findViewById(R.id.tv_fly_prepare_ele);
        mTvCapacity = view.findViewById(R.id.tv_fly_prepare_sd_capacity);
        mTvDistance = view.findViewById(R.id.tv_fly_prepare_take_off_distance);
        mTvMode = view.findViewById(R.id.tv_fly_prepare_fly_mode);
        mTvCampass = view.findViewById(R.id.tv_fly_prepare_compass);
        mTvIMU = view.findViewById(R.id.tv_fly_prepare_imu);
        mTvGPS = view.findViewById(R.id.tv_fly_prepare_gps);
        mTvResult = view.findViewById(R.id.tv_fly_prepare_result);
        mIvReduce = view.findViewById(R.id.iv_fly_prepare_speed_reduce);
        mIvPlus = view.findViewById(R.id.iv_fly_prepare_speed_plus);
        mSpFinishAction = view.findViewById(R.id.sp_fly_prepare_finish_action);
        mSpLoseCtrlAction = view.findViewById(R.id.sp_fly_prepare_lose_ctrl_action);
        mSbBar = view.findViewById(R.id.sb_fly_prepare_bar);
        mActivity = (RouteSettingActivity)getActivity();
        line = mActivity.line;
        handler = new Handler(this);
        initView();
        initData();
        addListener();
        initBattery();
//        checkFlightState();
        return view;
    }

    private void initBattery() {
        battery = MyApplication.getBatteryInstance();
        if (battery==null){
            return;
        }
//        battery.setStateCallback(this);
        if (battery != null) {
            //battery回调
            final int[] cap = new int[battery.size()];
            final int[] remain = new int[battery.size()];
            for (int i = 0; i < battery.size(); i++) {
                final int finalI = i;
                battery.get(i).setStateCallback(new BatteryState.Callback() {
                    @Override
                    public void onUpdate(BatteryState batteryState) {
                        //总电量
                        cap[finalI] = batteryState.getFullChargeCapacity();
                        remain[finalI] = batteryState.getChargeRemaining();
                        int sum = 0;
                        int rem = 0;
                        for (int j = 0; j < cap.length; j++) {
                            sum += cap[j];
                            rem =+ remain[j];
                        }
                        NumberFormat numberFormat = NumberFormat.getInstance();
                        numberFormat.setMaximumFractionDigits(2);
                        String result = numberFormat.format((float) rem / (float) sum * 100);
                        OnUIUtils.setTextView(mTvEle,result + "%");

                    }
                });
            }
        }
    }

    private void initView() {
        String action = line.getActionOnFinish();
        actionAdapter = new SpinnerDropDownAdapter(mActivity,R.layout.item_menu_blank,R.id.tv_item_menu_blank_tv,actions,3,mSpFinishAction);
        actionAdapter.setDropDownViewResource(R.layout.textview_spinner_drop_down_white);
        mSpFinishAction.setAdapter(actionAdapter);
        int motionPosition = 0;
        for (int i=0;i<actionIds.length;i++){
            if (action.equals(actionIds[i])){
                motionPosition = i;
            }
        }
        mSpFinishAction.setSelection(motionPosition);
        loseCtrlAdapter = new SpinnerDropDownAdapter(mActivity,R.layout.item_menu_blank,R.id.tv_item_menu_blank_tv,loseActions,3,mSpLoseCtrlAction);
        loseCtrlAdapter.setDropDownViewResource(R.layout.textview_spinner_drop_down_white);
        mSpLoseCtrlAction.setAdapter(loseCtrlAdapter);
        mSpLoseCtrlAction.setSelection(1);
    }

    private void addListener() {
        mTvCancel.setOnClickListener(this);
        mIvPlus.setOnClickListener(this);
        mIvReduce.setOnClickListener(this);

        mSpFinishAction.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                line.setActionOnFinish(actionIds[i]);
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });

        mSpLoseCtrlAction.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
//                line.setActionOnFinish(actionIds[i]);
                if (i==0){
                    line.setStopWhenLost(0);
                }else{
                    line.setStopWhenLost(1);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });

        mSbBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
                if (seekBarDragging){
                    speed = getSpeedFromProgress(progress);
                    line.setSpeed(speed);
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                seekBarDragging = true;
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                seekBarDragging = false;
            }
        });
    }

    private void initData() {

        speed = line.getSpeed();
        setSeekBarProgress(speed);

        mTvSpeed.setText(line.getSpeed()+"m/s");
        if (!mPref.getBoolean("dji_hardware",false)){
            return;
        }
        mFlightController = MyApplication.getFlightControllerInstance();
        if (mFlightController==null){
            return;
        }
        mTvMode.setText(mActivity.mFlightMode);
        if (mFlightController != null){
            int compassValue = mFlightController.getCompass().getCalibrationState().value();
            if (compassValue == CompassCalibrationState.NOT_CALIBRATING.value()){
                mTvCampass.setText("正常");
                compassOk = true;
            }else if (compassValue == CompassCalibrationState.HORIZONTAL.value()){
                mTvCampass.setText("水平");
                mTvResult.setEnabled(false);
            }else if (compassValue == CompassCalibrationState.VERTICAL.value()){
                mTvCampass.setText("垂直");
                mTvResult.setEnabled(false);
            }else if (compassValue == CompassCalibrationState.SUCCESSFUL.value()){
                mTvCampass.setText("成功");
                compassOk = true;
            }else if (compassValue == CompassCalibrationState.FAILED.value()){
                mTvCampass.setText("失败");

            }else if (compassValue == CompassCalibrationState.UNKNOWN.value()){
                mTvCampass.setText("未知");
                mTvResult.setEnabled(false);
            }
            imuOk = false;
            mFlightController.setIMUStateCallback(new IMUState.Callback() {
                @Override
                public void onUpdate(@NonNull IMUState imuState) {
                    SensorState sensorState = imuState.getGyroscopeState();
                    if (sensorState==SensorState.DISCONNECTED){
                        OnUIUtils.setTextView(mTvIMU,"断开连接");
                    }else if (sensorState==SensorState.CALIBRATING){
                        OnUIUtils.setTextView(mTvIMU,"正在校准");
                    }else if (sensorState==SensorState.CALIBRATION_FAILED){
                        OnUIUtils.setTextView(mTvIMU,"校准失败");
                    }else if (sensorState==SensorState.DATA_EXCEPTION){
                        OnUIUtils.setTextView(mTvIMU,"数据异常");
                    }else if (sensorState==SensorState.WARMING_UP){
                        OnUIUtils.setTextView(mTvIMU,"正在预热");
                    }else if (sensorState==SensorState.IN_MOTION){
                        OnUIUtils.setTextView(mTvIMU,"不够稳定");
                        imuOk = true;
                    }else if (sensorState==SensorState.NORMAL_BIAS){
                        OnUIUtils.setTextView(mTvIMU,"正常");
                        imuOk = true;
                    }else if (sensorState==SensorState.MEDIUM_BIAS){
                        OnUIUtils.setTextView(mTvIMU,"正常");
                        imuOk = true;
                    }else if (sensorState==SensorState.LARGE_BIAS){
                        OnUIUtils.setTextView(mTvIMU,"偏差值很大");
                    }
                    handler.sendEmptyMessage(0);

                }
            });
            getSDAvailableSize();
        }else{
            mTvCampass.setText("未知");
            mTvResult.setEnabled(false);
        }
        LatLng takeOffLatlng = new LatLng(mActivity.droneLocationLat,mActivity.droneLocationLng);

        if (takeOffLatlng.longitude<0||takeOffLatlng.latitude<0){
            mTvGPS.setText("GPS无法连接");
            mTvResult.setText("当前状态无法执行");
            mTvGPS.setTextColor(Color.RED);
            mTvResult.setTextColor(Color.RED);
            mTvResult.setClickable(false);
            gpsOk = false;
            mTvDistance.setText("无法定位飞行器位置");
        }else{
            RoutePoint point = mActivity.getPoint(0);
            LatLng startLatlng = new LatLng(point.getLatitude(),point.getLongitude());
            float distance = AMapUtils.calculateLineDistance(startLatlng,takeOffLatlng);
            mTvDistance.setText(DoubleUtils.doubleFormat(distance,0)+"m");
            mTvGPS.setText("GPS正常");
            mTvResult.setText("执行");
            mTvGPS.setTextColor(Color.GREEN);
            mTvResult.setTextColor(Color.GREEN);
            mTvResult.setClickable(true);
            gpsOk = true;
        }
        mTvResult.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mActivity.setWayPoints();
            }
        });
    }

    private void checkFlightState() {
        OnUIUtils.setToast("imu = "+imuOk+",gps ="+gpsOk+",compass = "+compassOk);
        if (imuOk&&gpsOk&&compassOk){
            mTvResult.setEnabled(true);
            mTvResult.setText("执行");
            mTvResult.setTextColor(mActivity.getResources().getColor(R.color.green));
        }else{
            mTvResult.setEnabled(false);
            mTvResult.setText("当前状态无法执行");
            mTvResult.setTextColor(mActivity.getResources().getColor(R.color.red));
        }
    }

    private void setSeekBarProgress(double speed) {
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        String percent = numberFormat.format((speed-1)/14*100);
        double d = Double.parseDouble(percent);
        progressPercent = (int) d;
        mSbBar.setProgress(progressPercent);
    }

    private double getSpeedFromProgress(int pogressPercent){
        double speed = 14*pogressPercent/100;
        speed = speed+1;
        return DoubleUtils.doubleFormat(speed,1);
    }

    private void getSDAvailableSize() {
        //获取手机SD卡容量
//        File path = Environment.getExternalStorageDirectory();
//        StatFs stat = new StatFs(path.getPath());
//        long blockSize = stat.getBlockSize();
//        long availableBlocks = stat.getAvailableBlocks();
//        return Formatter.formatFileSize(getActivity(), blockSize * availableBlocks);
        if (mPref.getBoolean("dji_hardware",false)){
            camera = MyApplication.getCameraInstance();
            camera.setStorageStateCallBack(new StorageState.Callback() {
                @Override
                public void onUpdate(@NonNull StorageState storageState) {
                    batteryCapacity = String.valueOf(storageState.getRemainingSpaceInMB());
                    mTvCapacity.setText(batteryCapacity+"MB");
                }
            });
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.tv_fly_prepare_cancel:
                mActivity.hidePrepareFragment();
                break;
            case R.id.iv_fly_prepare_speed_reduce:
                if (speed<=0){
                    return;
                }
                speed = DoubleUtils.doubleFormat(speed-0.1,2);
                if (speed<=1){
                    speed = 1;
                }
                setSeekBarProgress(speed);
                mActivity.getRouteLine().setSpeed(speed);
                mTvSpeed.setText(speed+"m/s");
                break;
            case R.id.iv_fly_prepare_speed_plus:
                speed =  DoubleUtils.doubleFormat(speed+0.1,2);
                if (speed>=15){
                    speed = 15;
                }
                setSeekBarProgress(speed);
                line.setSpeed(speed);
                mTvSpeed.setText(speed+"m/s");
                break;
        }
    }

    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what){
            case 0:
                checkFlightState();
                break;
        }
        return false;
    }
}
